#define BLINKER_WIFI
#define BLINKER_MIOT_MULTI_OUTLET

#define BLINKER_DUEROS_MULTI_OUTLET

#define BLINKER_ALIGENIE_MULTI_OUTLET

#define BLINKER_WITHOUT_SSL

#include <Blinker.h>

char auth[] = "39b725f9ce80";
char ssid[] = "Sweet_meng";
char pswd[] = "aita0116.";

BlinkerButton Button1("k1");
BlinkerButton Button2("k2");
BlinkerButton Button3("k3");
BlinkerButton Button4("k4");
BlinkerButton Button5("k5");

#define USB_F1 5
#define USB_F2 4
#define USB_F3 0
#define USB_F4 2
uint8_t num;
bool oState[5] = {false};

void heartbeat()
{
    BLINKER_LOG("heartbeat ,oState[0]: ", oState[0]);
    BLINKER_LOG("heartbeat ,oState[1]: ", oState[1]);
    BLINKER_LOG("heartbeat ,oState[2]: ", oState[2]);
    BLINKER_LOG("heartbeat ,oState[3]: ", oState[3]);
    BLINKER_LOG("heartbeat ,oState[4]: ", oState[4]);
    BLINKER_LOG("heartbeat ,oState[5]: ", oState[5]);

    if (HIGH == oState[1] || HIGH == oState[2] || HIGH == oState[3] || HIGH == oState[4])
    {
        oState[0] = true;
    }
    else
    {
        oState[0] = false;
    }

    if (HIGH == oState[0])
    {
        Button1.print("on");
    }
    else
    {
        Button1.print("off");
    }

    if (HIGH == oState[1])
    {
        Button2.print("on");
    }
    else
    {
        Button2.print("off");
    }

    if (HIGH == oState[2])
    {
        Button3.print("on");
    }
    else
    {
        Button3.print("off");
    }

    if (HIGH == oState[3])
    {
        Button4.print("on");
    }
    else
    {
        Button4.print("off");
    }

    if (HIGH == oState[4])
    {
        Button5.print("on");
    }
    else
    {
        Button5.print("off");
    }
}

void button1_callback(const String &state)
{
    BLINKER_LOG("get button state: ", state);
    if (state == BLINKER_CMD_ON)
    {
        BLINKER_LOG("Toggle all on!");
        Button1.print("on");
        Button2.print("on");
        Button3.print("on");
        Button4.print("on");
        Button5.print("on");
        digitalWrite(USB_F1, LOW);
        digitalWrite(USB_F2, LOW);
        digitalWrite(USB_F3, LOW);
        digitalWrite(USB_F4, LOW);
        oState[0] = true;
        oState[1] = true;
        oState[2] = true;
        oState[3] = true;
        oState[4] = true;
    }
    else if (state == BLINKER_CMD_OFF)
    {
        BLINKER_LOG("Toggle all off!");
        Button1.print("off");
        Button2.print("off");
        Button3.print("off");
        Button4.print("off");
        Button5.print("off");
        digitalWrite(USB_F1, HIGH);
        digitalWrite(USB_F2, HIGH);
        digitalWrite(USB_F3, HIGH);
        digitalWrite(USB_F4, HIGH);
        oState[0] = false;
        oState[1] = false;
        oState[2] = false;
        oState[3] = false;
        oState[4] = false;
    }
    BlinkerMIOT.powerState(oState[num] ? "on" : "off", num);
    BlinkerMIOT.print();

    BlinkerDuerOS.powerState(oState[num] ? "on" : "off", num);
    BlinkerDuerOS.print();

    BlinkerAliGenie.powerState(oState[num] ? "on" : "off", num);
    BlinkerAliGenie.print();
}

void button2_callback(const String &state)
{
    BLINKER_LOG("get button state: ", state);
    if (state == BLINKER_CMD_ON)
    {
        BLINKER_LOG("Toggle 1 on!");
        Button2.print("on");
        digitalWrite(USB_F1, LOW);
        oState[1] = true;
    }
    else if (state == BLINKER_CMD_OFF)
    {
        BLINKER_LOG("Toggle 1 off!");
        Button2.print("off");
        digitalWrite(USB_F1, HIGH);
        oState[1] = false;
    }
    BlinkerMIOT.powerState(oState[num] ? "on" : "off", num);
    BlinkerMIOT.print();

    BlinkerDuerOS.powerState(oState[num] ? "on" : "off", num);
    BlinkerDuerOS.print();

    BlinkerAliGenie.powerState(oState[num] ? "on" : "off", num);
    BlinkerAliGenie.print();
}

void button3_callback(const String &state)
{
    BLINKER_LOG("get button state: ", state);
    if (state == BLINKER_CMD_ON)
    {
        BLINKER_LOG("Toggle 2 on!");
        Button3.print("on");
        digitalWrite(USB_F2, LOW);
        oState[2] = true;
    }
    else if (state == BLINKER_CMD_OFF)
    {
        BLINKER_LOG("Toggle 2 off!");
        Button3.print("off");
        digitalWrite(USB_F2, HIGH);
        oState[2] = false;
    }
    BlinkerMIOT.powerState(oState[num] ? "on" : "off", num);
    BlinkerMIOT.print();

    BlinkerDuerOS.powerState(oState[num] ? "on" : "off", num);
    BlinkerDuerOS.print();

    BlinkerAliGenie.powerState(oState[num] ? "on" : "off", num);
    BlinkerAliGenie.print();
}

void button4_callback(const String &state)
{
    BLINKER_LOG("get button state: ", state);
    if (state == BLINKER_CMD_ON)
    {
        BLINKER_LOG("Toggle 3 on!");
        Button4.print("on");
        digitalWrite(USB_F3, LOW);
        oState[3] = true;
    }
    else if (state == BLINKER_CMD_OFF)
    {
        BLINKER_LOG("Toggle 3 off!");
        Button4.print("off");
        digitalWrite(USB_F3, HIGH);
        oState[3] = false;
    }
    BlinkerMIOT.powerState(oState[num] ? "on" : "off", num);
    BlinkerMIOT.print();

    BlinkerDuerOS.powerState(oState[num] ? "on" : "off", num);
    BlinkerDuerOS.print();

    BlinkerAliGenie.powerState(oState[num] ? "on" : "off", num);
    BlinkerAliGenie.print();
}

void button5_callback(const String &state)
{
    BLINKER_LOG("get button state: ", state);
    if (state == BLINKER_CMD_ON)
    {
        BLINKER_LOG("Toggle 4 on!");
        Button5.print("on");
        digitalWrite(USB_F4, LOW);
        oState[4] = true;
    }
    else if (state == BLINKER_CMD_OFF)
    {
        BLINKER_LOG("Toggle 4 off!");
        Button5.print("off");
        digitalWrite(USB_F4, HIGH);
        oState[4] = false;
    }
    BlinkerMIOT.powerState(oState[num] ? "on" : "off", num);
    BlinkerMIOT.print();

    BlinkerDuerOS.powerState(oState[num] ? "on" : "off", num);
    BlinkerDuerOS.print();

    BlinkerAliGenie.powerState(oState[num] ? "on" : "off", num);
    BlinkerAliGenie.print();
}

void miotPowerState(const String &state, uint8_t num)
{
    BLINKER_LOG("need set outlet: ", num, ", power state: ", state);
    if (state == BLINKER_CMD_ON)
    {
        if (num == 0)
        {
            digitalWrite(USB_F1, LOW);
            digitalWrite(USB_F2, LOW);
            digitalWrite(USB_F3, LOW);
            digitalWrite(USB_F4, LOW);
            oState[1] = true;
            oState[2] = true;
            oState[3] = true;
            oState[4] = true;
        }
        else if (num == 1)
        {
            digitalWrite(USB_F1, LOW);
        }
        else if (num == 2)
        {
            digitalWrite(USB_F2, LOW);
        }
        else if (num == 3)
        {
            digitalWrite(USB_F3, LOW);
        }
        else if (num == 4)
        {
            digitalWrite(USB_F4, LOW);
        }
        oState[num] = true;
    }
    else if (state == BLINKER_CMD_OFF)
    {
        if (num == 0)
        {
            digitalWrite(USB_F1, HIGH);
            digitalWrite(USB_F2, HIGH);
            digitalWrite(USB_F3, HIGH);
            digitalWrite(USB_F4, HIGH);
            oState[1] = false;
            oState[2] = false;
            oState[3] = false;
            oState[4] = false;
        }
        else if (num == 1)
        {
            digitalWrite(USB_F1, HIGH);
        }
        else if (num == 2)
        {
            digitalWrite(USB_F2, HIGH);
        }
        else if (num == 3)
        {
            digitalWrite(USB_F3, HIGH);
        }
        else if (num == 4)
        {
            digitalWrite(USB_F4, HIGH);
        }
        oState[num] = false;
    }
    BlinkerMIOT.powerState(oState[num] ? "on" : "off", num);
    BlinkerMIOT.print();
}

void miotQuery(int32_t queryCode, uint8_t num)
{
    BLINKER_LOG("MIOT Query outlet: ", num, ", codes: ", queryCode);

    switch (queryCode)
    {
    case BLINKER_CMD_QUERY_ALL_NUMBER:
        BLINKER_LOG("MIOT Query All");
        BlinkerMIOT.powerState(oState[num] ? "on" : "off", num);
        BlinkerMIOT.print();
        break;
    case BLINKER_CMD_QUERY_POWERSTATE_NUMBER:
        BLINKER_LOG("MIOT Query Power State");
        BlinkerMIOT.powerState(oState[num] ? "on" : "off", num);
        BlinkerMIOT.print();
        break;
    default:
        BlinkerMIOT.powerState(oState[num] ? "on" : "off", num);
        BlinkerMIOT.print();
        break;
    }
}

void duerPowerState(const String &state, uint8_t num)
{
    BLINKER_LOG("need set outlet: ", num, ", power state: ", state);
    if (state == BLINKER_CMD_ON)
    {
        if (num == 0)
        {
            digitalWrite(USB_F1, LOW);
            digitalWrite(USB_F2, LOW);
            digitalWrite(USB_F3, LOW);
            digitalWrite(USB_F4, LOW);
            oState[1] = true;
            oState[2] = true;
            oState[3] = true;
            oState[4] = true;
        }
        else if (num == 1)
        {
            digitalWrite(USB_F1, LOW);
        }
        else if (num == 2)
        {
            digitalWrite(USB_F2, LOW);
        }
        else if (num == 3)
        {
            digitalWrite(USB_F3, LOW);
        }
        else if (num == 4)
        {
            digitalWrite(USB_F4, LOW);
        }
        oState[num] = true;
    }
    else if (state == BLINKER_CMD_OFF)
    {
        if (num == 0)
        {
            digitalWrite(USB_F1, HIGH);
            digitalWrite(USB_F2, HIGH);
            digitalWrite(USB_F3, HIGH);
            digitalWrite(USB_F4, HIGH);
            oState[1] = false;
            oState[2] = false;
            oState[3] = false;
            oState[4] = false;
        }
        else if (num == 1)
        {
            digitalWrite(USB_F1, HIGH);
        }
        else if (num == 2)
        {
            digitalWrite(USB_F2, HIGH);
        }
        else if (num == 3)
        {
            digitalWrite(USB_F3, HIGH);
        }
        else if (num == 4)
        {
            digitalWrite(USB_F4, HIGH);
        }
        oState[num] = false;
    }
    BlinkerDuerOS.powerState(oState[num] ? "on" : "off", num);
    BlinkerDuerOS.print();
}

void duerQuery(int32_t queryCode, uint8_t num)
{
    BLINKER_LOG("DuerOS Query outlet:", num, ",codes:", queryCode);

    switch (queryCode)
    {
    case BLINKER_CMD_QUERY_ALL_NUMBER:
        BLINKER_LOG("DuerOS Query All");
        BlinkerDuerOS.powerState(oState[num] ? "on" : "off", num);
        BlinkerDuerOS.print();
        break;
    case BLINKER_CMD_QUERY_POWERSTATE_NUMBER:
        BLINKER_LOG("AliGenie Query Power State");
        BlinkerDuerOS.powerState(oState[num] ? "on" : "off", num);
        BlinkerDuerOS.print();
        break;
    default:
        BlinkerDuerOS.powerState(oState[num] ? "on" : "off", num);
        BlinkerDuerOS.print();
        break;
    }
}

void aligeniePowerState(const String &state, uint8_t num)
{
    BLINKER_LOG("need set outlet: ", num, ", power state: ", state);

    if (state == BLINKER_CMD_ON)
    {
        if (num == 0)
        {
            digitalWrite(USB_F1, LOW);
            digitalWrite(USB_F2, LOW);
            digitalWrite(USB_F3, LOW);
            digitalWrite(USB_F4, LOW);
            oState[1] = true;
            oState[2] = true;
            oState[3] = true;
            oState[4] = true;
        }
        else if (num == 1)
        {
            digitalWrite(USB_F1, LOW);
        }
        else if (num == 2)
        {
            digitalWrite(USB_F2, LOW);
        }
        else if (num == 3)
        {
            digitalWrite(USB_F3, LOW);
        }
        else if (num == 4)
        {
            digitalWrite(USB_F4, LOW);
        }
        oState[num] = true;
    }
    else if (state == BLINKER_CMD_OFF)
    {
        if (num == 0)
        {
            digitalWrite(USB_F1, HIGH);
            digitalWrite(USB_F2, HIGH);
            digitalWrite(USB_F3, HIGH);
            digitalWrite(USB_F4, HIGH);
            oState[1] = false;
            oState[2] = false;
            oState[3] = false;
            oState[4] = false;
        }
        else if (num == 1)
        {
            digitalWrite(USB_F1, HIGH);
        }
        else if (num == 2)
        {
            digitalWrite(USB_F2, HIGH);
        }
        else if (num == 3)
        {
            digitalWrite(USB_F3, HIGH);
        }
        else if (num == 4)
        {
            digitalWrite(USB_F4, HIGH);
        }
        oState[num] = false;
    }
    BlinkerAliGenie.powerState(oState[num] ? "on" : "off", num);
    BlinkerAliGenie.print();
}

void aligenieQuery(int32_t queryCode, uint8_t num)
{
    BLINKER_LOG("AliGenie Query outlet: ", num, ", codes: ", queryCode);

    switch (queryCode)
    {
    case BLINKER_CMD_QUERY_ALL_NUMBER:
        BLINKER_LOG("AliGenie Query All");
        BlinkerAliGenie.powerState(oState[num] ? "on" : "off", num);
        BlinkerAliGenie.print();
        break;
    case BLINKER_CMD_QUERY_POWERSTATE_NUMBER:
        BLINKER_LOG("AliGenie Query Power State");
        BlinkerAliGenie.powerState(oState[num] ? "on" : "off", num);
        BlinkerAliGenie.print();
        break;
    default:
        BlinkerAliGenie.powerState(oState[num] ? "on" : "off", num);
        BlinkerAliGenie.print();
        break;
    }
}

void dataRead(const String &data)
{
    BLINKER_LOG("Blinker readString: ", data);

    Blinker.vibrate();

    uint32_t BlinkerTime = millis();

    Blinker.print("millis", BlinkerTime);
}

void setup()
{
    Serial.begin(115200);
    BLINKER_DEBUG.stream(Serial);
    // BLINKER_DEBUG.debugAll();

    pinMode(USB_F1, OUTPUT);
    digitalWrite(USB_F1, HIGH);
    pinMode(USB_F2, OUTPUT);
    digitalWrite(USB_F2, HIGH);
    pinMode(USB_F3, OUTPUT);
    digitalWrite(USB_F3, HIGH);
    pinMode(USB_F4, OUTPUT);
    digitalWrite(USB_F4, HIGH);

    Button1.attach(button1_callback);
    Button2.attach(button2_callback);
    Button3.attach(button3_callback);
    Button4.attach(button4_callback);
    Button5.attach(button5_callback);
    Blinker.attachHeartbeat(heartbeat);

    Blinker.begin(auth, ssid, pswd);
    Blinker.attachData(dataRead);

    BlinkerMIOT.attachPowerState(miotPowerState);
    BlinkerMIOT.attachQuery(miotQuery);

    BlinkerDuerOS.attachPowerState(duerPowerState);
    BlinkerDuerOS.attachQuery(duerQuery);

    BlinkerAliGenie.attachPowerState(aligeniePowerState);
    BlinkerAliGenie.attachQuery(aligenieQuery);
}

void loop()
{
    Blinker.run();
}
